/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO_BUS;

import DataObject.MyColumn;
import DataObject.MyData;
import DataObject.MyRowData;
import java.util.Locale;
import java.util.Vector;
import org.w3c.dom.Document;

/**
 *
 * @author MinhNhat
 */
public class SelectSentence extends MySentence {

    private Vector Properties;
    private Vector Table;
    private Vector Conditions;
    public Vector Result;
    public Vector GroupByColumns;
    public Vector HavingConditions;

    public SelectSentence(String strSelect) {
        Result = new Vector();
        Properties = new Vector();
        GroupByColumns = new Vector();
        HavingConditions = new Vector();
        strSelect = strSelect.replaceAll("(\r\n|\n)", " ");

        strSelect = GetProperties(strSelect);

        Table = new Vector();
        strSelect = GetTable(strSelect);

        Conditions = new Vector();
        if (strSelect.length() > 0) {
            Conditions = this.GetConditions(strSelect);
        }

        if (strSelect.length() > 0) {
            strSelect = GetGroupBy(strSelect);
        }

        if (strSelect.length() > 0) {
            HavingConditions = this.GetHavingConditions(strSelect);
        }
    }

    private String GetProperties(String str) {
        str = str.trim();

        String s1 = str.toLowerCase();
        String s2 = "select ";
        int indexOfProperty = s1.indexOf(s2);
        String s3 = " from ";
        int indexOfEndProperty = s1.indexOf(s3);

        if (indexOfProperty == -1 || indexOfEndProperty == -1) {
            return str;
        }

        String core = str.substring(indexOfProperty + s2.length(), indexOfEndProperty).trim();
        String[] temp = core.split(",");
        for (int i = 0; i < temp.length; i++) {
            String property = temp[i].trim();
            String strAs = " as ";
            if (property.toLowerCase().contains(strAs)) {
                String currentName, newName;
                int indexEndCurrentName, indexBeginCurrentName;
                indexEndCurrentName = property.toLowerCase().indexOf(strAs);
                indexBeginCurrentName = indexEndCurrentName + strAs.length();

                currentName = property.substring(0, indexEndCurrentName).trim();
                newName = property.substring(indexBeginCurrentName, property.length()).trim();
                MyPropertySelect Property = new MyPropertySelect(currentName, newName);
                Properties.add(Property);
            } else {
                MyPropertySelect Property = new MyPropertySelect(temp[i].trim(), "");
                Properties.add(Property);
            }

        }

        return str.substring(indexOfEndProperty + s3.length(), str.length()).trim();
    }

    private String GetTable(String str) {
        str = str.trim();

        String s1 = str.toLowerCase();
        String s2 = " where ";
        int indexOfEndTable = s1.indexOf(s2);

        if (indexOfEndTable == -1) {
            indexOfEndTable = s1.indexOf(" group ");
            if (indexOfEndTable == -1) {
                if (!str.isEmpty()) {
                    Table.add(str);
                    return "";
                }
            }


        }
        String core = str.substring(0, indexOfEndTable).trim();

        String[] temp = core.split(",");
        for (int i = 0; i < temp.length; i++) {
            Table.add(temp[i].trim());
        }
        return str.substring(indexOfEndTable, str.length()).trim();
    }

    public String GetGroupBy(String str) {
        str = str.trim();
        String strLC = str.toLowerCase();

        if (!(strLC.indexOf("group ") > -1 && strLC.indexOf("group ") < strLC.indexOf(" by "))) {
            return "";
        }

        int indexBeginSentenceGB, indexEndSentenceGB;
        indexBeginSentenceGB = indexEndSentenceGB = -1;
        String strTest = " by ";
        indexBeginSentenceGB = strLC.indexOf(strTest) + strTest.length();
        indexEndSentenceGB = strLC.indexOf(" having ", indexBeginSentenceGB);
        if (indexEndSentenceGB == -1) {
            indexEndSentenceGB = str.length();
        }

        String strSentenceGB = str.substring(indexBeginSentenceGB, indexEndSentenceGB).trim();
        String[] parts = strSentenceGB.split(",");
        for (int i = 0; i < parts.length; i++) {
            GroupByColumns.add(parts[i].trim());
        }

        return str.substring(indexEndSentenceGB, str.length()).trim();
    }

    public Vector GetHavingConditions(String str) {
        Vector Conditions = new Vector();
        String s1 = str.toLowerCase();
        String s2 = " having ";
        int indexOfStart = s1.indexOf(s2);
        if (indexOfStart == -1) {
            return Conditions;
        }

        str = str.substring(indexOfStart + s2.length(), str.length()).trim();

        String[] Relation = {" and ", " or "};

        while (str.length() != 0) {
            int i;
            int indexOfRelation = -1;
            String strLower = str.toLowerCase();
            for (i = 0; i < Relation.length; i++) {
                indexOfRelation = strLower.indexOf(Relation[i]);
                if (indexOfRelation != -1) {
                    break;
                }
            }

            MyExpression express;
            if (indexOfRelation != -1) {
                String temp = str.substring(0, indexOfRelation);
                express = new MyExpression(temp);
                express.Relationship = Relation[i];
                str = str.substring(indexOfRelation + Relation[i].length(), str.length()).trim();
            } else {
                express = new MyExpression(str.trim());
                express.Relationship = "";
                str = "";
            }

            Conditions.add(express);
        }

        return Conditions;
    }

    public boolean FormatConditions(Vector Tables) {
        for (int i = 0; i < Conditions.size(); i++) {
            MyExpression Expression = (MyExpression) Conditions.get(i);
            Expression.LeftSide = FormatStringCondition(Expression.LeftSide, Tables).trim();
            Expression.RightSide = FormatStringCondition(Expression.RightSide, Tables).trim();
            if (Expression.LeftSide.isEmpty() || Expression.RightSide.isEmpty()) {
                return false;
            }
        }
        return true;

    }

    public Vector KetTatCaCacBang(Vector Tables) {
        Vector results = new Vector();
        Vector TablesOfDatabase = GetAllTableOfSelect(Tables);
        for (int i = 0; i < TablesOfDatabase.size(); i++) {
            MyTable table = (MyTable) TablesOfDatabase.get(i);
            results = KetTable(table, results);
        }
        return results;
    }

    public Vector KetTable(MyTable Table1, Vector Results) {
        Vector Data1 = Table1.GetData();
        if (Results.size() == 0) {
            for (int i = 0; i < Data1.size(); i++) {
                MySelectResult result = new MySelectResult();
                result.Data.add(Data1.get(i));
                Results.add(result);
            }
            return Results;
        } else {
            Vector Source = new Vector();
            for (int i = 0; i < Results.size(); i++) {
                MySelectResult result = (MySelectResult) Results.get(i);
                for (int j = 0; j < Data1.size(); j++) {
                    MySelectResult temp = new MySelectResult();
                    for (int k = 0; k < result.Data.size(); k++) {
                        temp.Data.add(result.Data.get(k));
                    }
                    temp.Data.add(Data1.get(j));
                    Source.add(temp);
                }
            }
            return Source;


        }


    }

    /*
     * public Vector GetVarOfFromPart() { Vector Vars = new Vector(); for (int i
     * = 0; i < Table.size(); i++) { String temp = (String) Table.get(i); if
     * (temp.contains(" ")) { String[] parts = temp.split(" "); if (parts.length
     * == 2) { Vars.add(parts[1]); } } } return Vars;
    }
     */
    public Vector GetAllTableOfSelect(Vector Tables) {
        Vector tables = new Vector();
        for (int i = 0; i < Table.size(); i++) {
            String name = (String) Table.get(i);
            if (name.contains(".")) {
                String[] temp = name.replace(".", " ").split(" ");
                name = temp[0];
            }
            MyTable temp = MyTable.GetTableByName(Tables, name);
            tables.add(temp);
        }
        return tables;
    }

    public String FormatStringCondition(String str, Vector Tables) {
        if (str.contains(".") && !str.contains("'")) {
            str = str.replace(" ", "");
            String temp = str.replace(".", " ");
            String[] list = temp.split(" ");

            boolean flag = false;
            for (int j = 0; j < Table.size(); j++) {
                String table = (String) Table.get(j);
                String[] parts = table.replace(".", ":").split(":");
                if (parts[parts.length - 1].trim().compareTo(list[0]) == 0) {
                    if (parts.length == 2) {
                        str = parts[0] + "." + parts[1] + "." + list[list.length - 1];
                    }

                    if (parts.length == 1) {
                        str = parts[0] + "." + list[list.length - 1];
                    }

                    flag = true;
                    break;
                }
            }

            if (!flag) {
                return "";
            }
        } else {
            if (MySentence.isCharacter(str) && !str.contains("'")) {
                for (int j = 0; j < Tables.size(); j++) {
                    MyTable table = (MyTable) Tables.get(j);

                    for (int k = 0; k < Table.size(); k++) {
                        if (table.GetName().compareTo((String) Table.get(k)) == 0 && table.isContainColumn(str)) {
                            str = table.GetName() + "." + str;
                            return str;
                        }
                    }

                }
            }
        }
        return str;
    }

    public static boolean isSelectSentence(String str) {
        String s1 = str.toLowerCase().trim();
        String s2 = "select ";
        int indexOfString = s1.indexOf(s2);
        if (indexOfString == 0) {
            return true;
        }
        return false;
    }

    public boolean FormatFromTable(Vector Tables) {

        Vector tempTable = new Vector();
        for (int i = 0; i < Table.size(); i++) {
            String table = (String) Table.get(i);


            if (!MySentence.isContainJoin(table)) {
                String parts[] = table.split(" ");
                String NameTable;
                if (parts.length == 1) {
                    NameTable = table.trim();

                } else {
                    table = parts[0] + "." + parts[parts.length - 1];
                    NameTable = parts[0].trim();
                }
                boolean flag = false;
                for (int j = 0; j < Tables.size(); j++) {
                    MyTable tableOfDB = (MyTable) Tables.get(j);

                    String abc = tableOfDB.GetName();
                    if (tableOfDB.GetName().compareTo(NameTable) == 0) {
                        flag = true;
                        break;
                    }
                }

                if (!flag) {
                    return false;
                }
                Table.set(i, table);
            } else {
                int indexOfTable1, indexOfEndTable1, indexOfTable2, indexOfEndTable2;
                indexOfTable1 = indexOfEndTable1 = indexOfTable2 = indexOfEndTable2 = -1;
                String temp = table.toLowerCase();
                indexOfTable1 = 0;

                String temp1 = " join ";
                indexOfEndTable1 = temp.indexOf(temp1);


                if (indexOfEndTable1 == -1) {
                    return false;
                }
                indexOfTable2 = indexOfEndTable1 + temp1.length();

                indexOfEndTable2 = temp.indexOf(" on ");

                if (indexOfEndTable2 == -1) {
                    return false;
                }

                if (indexOfEndTable2 < indexOfEndTable1) {
                    return false;
                }

                String nameOfTable1, nameOfTable2;
                nameOfTable1 = table.substring(indexOfTable1, indexOfEndTable1).trim();
                nameOfTable2 = table.substring(indexOfTable2, indexOfEndTable2).trim();

                Table.set(i, nameOfTable1);
                Table.add(nameOfTable2);
                tempTable.add(nameOfTable1);
                String temp2 = " on ";
                int indexOfConditionJoin = table.toLowerCase().indexOf(temp2, indexOfEndTable2);
                if (indexOfConditionJoin == -1) {
                    return false;
                }

                String condition = table.substring(indexOfConditionJoin + temp2.length(), table.length()).trim();
                Conditions.add(new MyExpression(condition));
            }


        }
        return true;
    }

    public void FormatProperties(Vector Tables) {
        for (int i = 0; i < Properties.size(); i++) {
            MyPropertySelect Property = (MyPropertySelect) Properties.get(i);
            String property = Property.NameColumn;

            String propertyCandidate = this.GetColumnInSpecialProperties(property);
            if (!propertyCandidate.isEmpty()) {
                property = propertyCandidate;
            }

            if (property.contains(".")) {
                String[] parts = property.replace(".", " ").split(" ");
                for (int j = 0; j < Table.size(); j++) {
                    String FromTable = (String) Table.get(j);
                    if (FromTable.contains(".")) {
                        String[] partsFromTable = FromTable.replace(".", " ").split(" ");
                        if (partsFromTable[partsFromTable.length - 1].compareTo(parts[0]) == 0 || parts[1].compareTo("*") == 0) {
                            property = partsFromTable[0] + "." + property;
                            break;
                        }
                    }

                }
            } else {
                for (int j = 0; j < Table.size(); j++) {
                    String FromTable = (String) Table.get(j);
                    String NameTable;
                    if (FromTable.contains(".")) {
                        String[] partsOfFromTable = FromTable.replace(".", " ").split(" ");
                        NameTable = partsOfFromTable[0];
                    } else {
                        NameTable = FromTable;
                    }

                    MyColumn Column = MyTable.GetColumn(Tables, NameTable, property);
                    if (Column != null || property.compareTo("*") == 0) {
                        property = FromTable + "." + property;
                    }

                }
            }

            if (propertyCandidate.isEmpty()) {
                Property.NameColumn = property;
            } else {
                Property.NameColumn = Property.NameColumn.replace(propertyCandidate, property);
            }

            //Properties.set(i, property);
        }
    }

    public void FormatGroupBy(Vector Tables) {
        for (int i = 0; i < GroupByColumns.size(); i++) {
            String column = (String) GroupByColumns.get(i);
            if (column.contains(".")) {
                String[] parts = column.replace(".", ":").split(":");
                for (int j = 0; j < Table.size(); j++) {
                    String FromTable = (String) Table.get(j);
                    if (FromTable.contains(".")) {
                        String[] partsFromTable = FromTable.replace(".", ":").split(":");
                        if (partsFromTable[partsFromTable.length - 1].compareTo(parts[0]) == 0 || parts[1].compareTo("*") == 0) {
                            column = partsFromTable[0] + "." + column;
                            break;
                        }
                    }

                }
            } else {
                for (int j = 0; j < Table.size(); j++) {
                    String FromTable = (String) Table.get(j);
                    String NameTable;
                    if (FromTable.contains(".")) {
                        String[] partsOfFromTable = FromTable.replace(".", ":").split(":");
                        NameTable = partsOfFromTable[0];
                    } else {
                        NameTable = FromTable;
                    }

                    MyColumn Column = MyTable.GetColumn(Tables, NameTable, column);
                    if (Column != null) {
                        column = FromTable + "." + column;
                        break;
                    }

                }
            }

            System.out.println(column);
            if (column.contains(".")) {
                GroupByColumns.set(i, column);
            } else {
                GroupByColumns.set(i, "");
            }
        }
    }

    public void FormatHaving(Vector Tables) {
        for (int i = 0; i < HavingConditions.size(); i++) {
            MyExpression express = (MyExpression) HavingConditions.get(i);
            // Left Side
            String property = express.LeftSide;

            String propertyCandidate = this.GetColumnInSpecialProperties(property);
            if (!propertyCandidate.isEmpty()) {
                property = propertyCandidate;
            }

            if (property.contains(".")) {
                String[] parts = property.replace(".", " ").split(" ");
                for (int j = 0; j < Table.size(); j++) {
                    String FromTable = (String) Table.get(j);
                    if (FromTable.contains(".")) {
                        String[] partsFromTable = FromTable.replace(".", " ").split(" ");
                        if (partsFromTable[partsFromTable.length - 1].compareTo(parts[0]) == 0 || parts[1].compareTo("*") == 0) {
                            property = partsFromTable[0] + "." + property;
                            break;
                        }
                    }

                }
            } else {
                for (int j = 0; j < Table.size(); j++) {
                    String FromTable = (String) Table.get(j);
                    String NameTable;
                    if (FromTable.contains(".")) {
                        String[] partsOfFromTable = FromTable.replace(".", " ").split(" ");
                        NameTable = partsOfFromTable[0];
                    } else {
                        NameTable = FromTable;
                    }

                    MyColumn Column = MyTable.GetColumn(Tables, NameTable, property);
                    if (Column != null || property.compareTo("*") == 0) {
                        property = FromTable + "." + property;
                    }

                }
            }

            if (propertyCandidate.isEmpty()) {
                express.LeftSide = property;
            } else {
                express.LeftSide = express.LeftSide.replace(propertyCandidate, property);
            }


            //Right Side
            property = express.RightSide;

            propertyCandidate = this.GetColumnInSpecialProperties(property);
            if (!propertyCandidate.isEmpty()) {
                property = propertyCandidate;
            }

            if (property.contains(".")) {
                String[] parts = property.replace(".", " ").split(" ");
                for (int j = 0; j < Table.size(); j++) {
                    String FromTable = (String) Table.get(j);
                    if (FromTable.contains(".")) {
                        String[] partsFromTable = FromTable.replace(".", " ").split(" ");
                        if (partsFromTable[partsFromTable.length - 1].compareTo(parts[0]) == 0 || parts[1].compareTo("*") == 0) {
                            property = partsFromTable[0] + "." + property;
                            break;
                        }
                    }

                }
            } else {
                for (int j = 0; j < Table.size(); j++) {
                    String FromTable = (String) Table.get(j);
                    String NameTable;
                    if (FromTable.contains(".")) {
                        String[] partsOfFromTable = FromTable.replace(".", " ").split(" ");
                        NameTable = partsOfFromTable[0];
                    } else {
                        NameTable = FromTable;
                    }

                    MyColumn Column = MyTable.GetColumn(Tables, NameTable, property);
                    if (Column != null || property.compareTo("*") == 0) {
                        property = FromTable + "." + property;
                    }

                }
            }

            if (propertyCandidate.isEmpty()) {
                express.RightSide = property;
            } else {
                express.RightSide = express.RightSide.replace(propertyCandidate, property);
            }
        }
    }

    public boolean Excute(Document doc, Vector Tables, Vector ResultOut) {
        try {
            if (!FormatFromTable(Tables)) {
                return false;
            }
            if (!FormatConditions(Tables)) {
                return false;
            }
            FormatProperties(Tables);
            FormatGroupBy(Tables);
            FormatHaving(Tables);
            if (Table.size() == 0 || Properties.size() == 0) {
                return false;
            }

            Vector Datas = KetTatCaCacBang(Tables);


            for (int i = 0; i < Datas.size(); i++) {
                Vector conditions = new Vector();
                conditions = (Vector) Conditions.clone();

                MySelectResult temp = (MySelectResult) Datas.get(i);
                if (temp.CheckCondition(conditions, Table)) {
                    Result.add(temp);
                }
            }


            Vector temp = ParseResult(Result, Tables);

            temp = ProcessResult(temp);

            if (!HavingConditions.isEmpty() && !temp.isEmpty()) {
                temp = ProcessHaving(temp);
            }


            ResultOut.addAll(temp);
        } catch (Exception ex) {
            System.out.println(ex.toString());
            return false;
        }
        return true;
    }

    public Vector ParseResult(Vector Results, Vector Tables) {
        Vector Rows = new Vector();
        for (int i = 0; i < Results.size(); i++) {
            MySelectResult Result = (MySelectResult) Results.get(i);
            MyRowData Row = Result.GetValue(Tables, Table, Properties, GroupByColumns);
            Rows.add(Row);
        }
        return Rows;
    }

    public boolean isContainIgnoreCase(String str, String sub) {
        return str.toLowerCase().contains(sub.toLowerCase());
    }

    public static String GetColumnInSpecialProperties(String str) {
        String[] SpecialProperties = {"max", "min", "sum", "avg"};
        String strLC = str.toLowerCase();
        for (int i = 0; i < SpecialProperties.length; i++) {
            if (strLC.contains(SpecialProperties[i])) {
                int indexBegin, indexEnd;
                indexBegin = indexEnd = -1;
                indexBegin = strLC.indexOf(SpecialProperties[i]) + SpecialProperties[i].length();
                indexBegin = str.indexOf("(", indexBegin) + 1;
                indexEnd = str.lastIndexOf(")");
                return str.substring(indexBegin, indexEnd);
            }
        }
        return "";
    }

    public Vector ProcessResult(Vector Result) {
        Vector FinalResult = new Vector();
        boolean flag = false;

        for (int i = 0; i < Properties.size(); i++) {
            MyPropertySelect property = (MyPropertySelect) Properties.get(i);
            String columnInProperty = SelectSentence.GetColumnInSpecialProperties(property.NameColumn);
            if (columnInProperty.isEmpty()) {
                continue;
            }
            flag = true;
            String functionName = property.NameColumn.replace(columnInProperty, "").replace(" ", "").toLowerCase();

            Vector ResultAdded = new Vector();
            if (functionName.contains("max()")) {
                ResultAdded = ProcessMax(Result, property, columnInProperty);
            }

            if (functionName.contains("min()")) {
                ResultAdded = ProcessMin(Result, property, columnInProperty);
            }

            if (functionName.contains("sum()")) {
                ResultAdded = ProcessSum(Result, property, columnInProperty);
            }

            if (functionName.contains("avg()")) {
                ResultAdded = ProcessAVG(Result, property, columnInProperty);
            }

            FinalResult = this.MergeResult(FinalResult, ResultAdded);
        }

        if (!flag) {
            return Result;
        } else {
            return FinalResult;
        }
    }

    public Vector ProcessHaving(Vector Result) {
        Vector FinalResult = new Vector();

        if (Result.isEmpty()) {
            return FinalResult;
        }

        MyRowData RowModel = (MyRowData) Result.get(0);


        for (int i = 0; i < HavingConditions.size(); i++) {
            MyExpression express = (MyExpression) HavingConditions.get(i);
            String strLeft, strRight;
            strLeft = express.LeftSide;
            strRight = express.RightSide;

            if (SelectSentence.GetColumnInSpecialProperties(express.LeftSide).isEmpty()) {
                strLeft = express.LeftSide;
            } else {
                boolean flag = false;
                for (int j = 0; j < Properties.size(); j++) {
                    MyPropertySelect property = (MyPropertySelect) Properties.get(j);
                    if (property.NameColumn.compareTo(express.LeftSide) == 0) {
                        if (!property.NewNameColumn.isEmpty()) {
                            strLeft = property.NewNameColumn;
                            flag = true;
                            break;
                        }
                    }
                }

                if (!flag) {
                    String core = SelectSentence.GetColumnInSpecialProperties(express.LeftSide);
                    String[] parts = core.replace(".", ":").split(":");
                    strLeft = parts[parts.length - 1];
                }
            }

            //Right Side 
            if (SelectSentence.GetColumnInSpecialProperties(express.RightSide).isEmpty()) {
                strRight = express.RightSide;
            } else {
                boolean flag = false;
                for (int j = 0; j < Properties.size(); j++) {
                    MyPropertySelect property = (MyPropertySelect) Properties.get(j);
                    if (property.NameColumn.compareTo(express.RightSide) == 0) {
                        if (!property.NewNameColumn.isEmpty()) {
                            strRight = property.NewNameColumn;
                            flag = true;
                            break;
                        }
                    }
                }

                if (!flag) {
                    String core = SelectSentence.GetColumnInSpecialProperties(express.RightSide);
                    String[] parts = core.replace(".", ":").split(":");
                    strRight = parts[parts.length - 1];
                }
            }

            if (MySentence.isCharacter(strLeft)) {
                express.LeftSide = strLeft;
            } else {
                express.LeftSide = "'" + strLeft + "'";
            }

            if (MySentence.isCharacter(strRight)) {
                express.RightSide = strRight;
            } else {
                express.RightSide = "'" + strRight + "'";
            }

        }

        for (int i = 0; i < Result.size(); i++) {
            MyRowData Row = (MyRowData) Result.get(i);
            Vector Conditions = (Vector) HavingConditions.clone();
            if (MyExpression.GetTheTruth(Conditions, Row) != 0) {
                FinalResult.add(Row);
            }
        }
        return FinalResult;
    }

    public Vector ProcessMax(Vector Result, MyPropertySelect property, String columnInProperty) {
        Vector FinalResult = new Vector();
        MyGroupByColumn GroupByValues = new MyGroupByColumn();


        for (int j = 0; j < Result.size(); j++) {
            MyRowData Row = (MyRowData) Result.get(j);

            String nameColumn;
            if (property.NewNameColumn.isEmpty()) {
                String[] parts = columnInProperty.replace(".", ":").split(":");
                nameColumn = parts[parts.length - 1];
            } else {
                nameColumn = property.NewNameColumn;
            }
            MyData Data = Row.GetData(nameColumn);

            if (Data == null) {
                return FinalResult;
            }

            if (!Data.isInteger()) {
                // khong xu ly duoc
                return FinalResult;
            }


            Vector Values = new Vector();
            if (GroupByColumns.size() == 0) {
                GroupByValues.Add(Values, Data.Value, j);
            } else {
                for (int k = 0; k < GroupByColumns.size(); k++) {
                    String nameColumnGroup = (String) GroupByColumns.get(k);
                    String[] parts = nameColumnGroup.replace(".", ":").split(":");
                    String NameOFColumn = parts[parts.length - 1];
                    MyData DataAtGroupByColumn = (MyData) Row.GetData(NameOFColumn);
                    if (DataAtGroupByColumn != null) {
                        Values.add(DataAtGroupByColumn.Value);
                    }
                }

                GroupByValues.Add(Values, Data.Value, j);
            }

        }

        //Tim Max
        Vector MaxValues = new Vector();
        for (int i = 0; i < GroupByValues.Values.size(); i++) {
            MyGroupByValue Value = (MyGroupByValue) GroupByValues.Values.get(i);
            int max = Integer.MIN_VALUE;
            for (int j = 0; j < Value.Data.size(); j++) {
                int value = Integer.parseInt(Value.Data.get(j).toString());
                if (value > max) {
                    max = value;
                }
            }
            MaxValues.add(max);
        }

        for (int i = 0; i < MaxValues.size(); i++) {
            int max = (int) MaxValues.get(i);
            MyGroupByValue Value = (MyGroupByValue) GroupByValues.Values.get(i);
            for (int j = 0; j < Value.Data.size(); j++) {
                int value = Integer.parseInt(Value.Data.get(j).toString());
                if (value == max) {
                    int index = (int) Value.Index.get(j);
                    FinalResult.add(Result.get(index));
                }
            }
        }

        return FinalResult;
    }

    public Vector ProcessMin(Vector Result, MyPropertySelect property, String columnInProperty) {
        Vector FinalResult = new Vector();
        MyGroupByColumn GroupByValues = new MyGroupByColumn();


        for (int j = 0; j < Result.size(); j++) {
            MyRowData Row = (MyRowData) Result.get(j);

            String nameColumn;
            if (property.NewNameColumn.isEmpty()) {
                String[] parts = columnInProperty.replace(".", ":").split(":");
                nameColumn = parts[parts.length - 1];
            } else {
                nameColumn = property.NewNameColumn;
            }
            MyData Data = Row.GetData(nameColumn);

            if (Data == null) {
                return FinalResult;
            }

            if (!Data.isInteger()) {
                // khong xu ly duoc
                return FinalResult;
            }


            Vector Values = new Vector();
            if (GroupByColumns.size() == 0) {
                GroupByValues.Add(Values, Data.Value, j);
            } else {
                for (int k = 0; k < GroupByColumns.size(); k++) {
                    String nameColumnGroup = (String) GroupByColumns.get(k);
                    String[] parts = nameColumnGroup.replace(".", ":").split(":");
                    String NameOFColumn = parts[parts.length - 1];
                    MyData DataAtGroupByColumn = (MyData) Row.GetData(NameOFColumn);
                    if (DataAtGroupByColumn != null) {
                        Values.add(DataAtGroupByColumn.Value);
                    }
                }

                GroupByValues.Add(Values, Data.Value, j);
            }

        }



        //Tim Min
        Vector MaxValues = new Vector();
        for (int i = 0; i < GroupByValues.Values.size(); i++) {
            MyGroupByValue Value = (MyGroupByValue) GroupByValues.Values.get(i);
            int min = Integer.MAX_VALUE;
            for (int j = 0; j < Value.Data.size(); j++) {
                int value = Integer.parseInt(Value.Data.get(j).toString());
                if (value < min) {
                    min = value;
                }
            }
            MaxValues.add(min);
        }

        for (int i = 0; i < MaxValues.size(); i++) {
            int min = (int) MaxValues.get(i);
            MyGroupByValue Value = (MyGroupByValue) GroupByValues.Values.get(i);
            for (int j = 0; j < Value.Data.size(); j++) {
                int value = Integer.parseInt(Value.Data.get(j).toString());
                if (value == min) {
                    int index = (int) Value.Index.get(j);
                    FinalResult.add(Result.get(index));
                }
            }
        }

        return FinalResult;
    }

    public Vector ProcessSum(Vector Result, MyPropertySelect property, String columnInProperty) {
        Vector FinalResult = new Vector();
        MyGroupByColumn GroupByValues = new MyGroupByColumn();
        String nameColumn = "unknown";
        for (int j = 0; j < Result.size(); j++) {
            MyRowData Row = (MyRowData) Result.get(j);

            if (property.NewNameColumn.isEmpty()) {
                String[] parts = columnInProperty.replace(".", ":").split(":");
                nameColumn = parts[parts.length - 1];
            } else {
                nameColumn = property.NewNameColumn;
            }
            MyData Data = Row.GetData(nameColumn);

            if (Data == null) {
                return FinalResult;
            }

            if (!Data.isInteger()) {
                // khong xu ly duoc
                return FinalResult;
            }


            Vector Values = new Vector();
            if (GroupByColumns.size() == 0) {
                GroupByValues.Add(Values, Data.Value, j);
            } else {
                for (int k = 0; k < GroupByColumns.size(); k++) {
                    String nameColumnGroup = (String) GroupByColumns.get(k);
                    String[] parts = nameColumnGroup.replace(".", ":").split(":");
                    String NameOFColumn = parts[parts.length - 1];
                    MyData DataAtGroupByColumn = (MyData) Row.GetData(NameOFColumn);
                    if (DataAtGroupByColumn != null) {
                        Values.add(DataAtGroupByColumn.Value);
                    }
                }

                GroupByValues.Add(Values, Data.Value, j);
            }

        }


        for (int i = 0; i < GroupByValues.Values.size(); i++) {
            MyGroupByValue Value = (MyGroupByValue) GroupByValues.Values.get(i);
            int sum = 0;
            for (int j = 0; j < Value.Data.size(); j++) {
                int value = Integer.parseInt(Value.Data.get(j).toString());
                sum += value;
            }

            int index = (int) Value.Index.get(0);
            MyRowData Row = (MyRowData) Result.get(index);
            MyData data = Row.GetData(nameColumn);
            data.Value = String.valueOf(sum);
            FinalResult.add(Row);
        }



        return FinalResult;
    }

    public Vector ProcessAVG(Vector Result, MyPropertySelect property, String columnInProperty) {
        Vector FinalResult = new Vector();
        MyGroupByColumn GroupByValues = new MyGroupByColumn();
        String nameColumn = "unknown";
        for (int j = 0; j < Result.size(); j++) {
            MyRowData Row = (MyRowData) Result.get(j);

            if (property.NewNameColumn.isEmpty()) {
                String[] parts = columnInProperty.replace(".", ":").split(":");
                nameColumn = parts[parts.length - 1];
            } else {
                nameColumn = property.NewNameColumn;
            }
            MyData Data = Row.GetData(nameColumn);

            if (Data == null) {
                return FinalResult;
            }

            if (!Data.isInteger()) {
                // khong xu ly duoc
                return FinalResult;
            }


            Vector Values = new Vector();
            if (GroupByColumns.size() == 0) {
                GroupByValues.Add(Values, Data.Value, j);
            } else {
                for (int k = 0; k < GroupByColumns.size(); k++) {
                    String nameColumnGroup = (String) GroupByColumns.get(k);
                    String[] parts = nameColumnGroup.replace(".", ":").split(":");
                    String NameOFColumn = parts[parts.length - 1];
                    MyData DataAtGroupByColumn = (MyData) Row.GetData(NameOFColumn);
                    if (DataAtGroupByColumn != null) {
                        Values.add(DataAtGroupByColumn.Value);
                    }
                }

                GroupByValues.Add(Values, Data.Value, j);
            }

        }


        for (int i = 0; i < GroupByValues.Values.size(); i++) {
            MyGroupByValue Value = (MyGroupByValue) GroupByValues.Values.get(i);
            int sum = 0;
            for (int j = 0; j < Value.Data.size(); j++) {
                int value = Integer.parseInt(Value.Data.get(j).toString());
                sum += value;
            }

            float avg = (float) sum / Value.Data.size();
            int index = (int) Value.Index.get(0);
            MyRowData Row = (MyRowData) Result.get(index);
            MyData data = Row.GetData(nameColumn);
            data.Value = String.valueOf(avg);
            FinalResult.add(Row);
        }

        return FinalResult;
    }

    public Vector MergeResult(Vector OldResult, Vector NewResult) {
        Vector FinalResult = new Vector();
        for (int i = 0; i < NewResult.size(); i++) {
            if (OldResult.contains(NewResult.get(i)) || OldResult.isEmpty()) {
                FinalResult.add(NewResult.get(i));
            }
        }
        return FinalResult;
    }
}
